import { Inject, Provide, Config } from "@midwayjs/core";
import { JwtService } from "@midwayjs/jwt";
import { Context } from "@midwayjs/koa";
import { CaptchaService } from "@midwayjs/captcha";
import { Utils } from "../utils";
import { Repository } from "typeorm";
import { InjectEntityModel } from "@midwayjs/typeorm";
import { User } from "../entity/user.entity";
import { UserService } from "./user.service";

@Provide()
export class AuthService {
  @Inject()
  jwtService: JwtService;

  @Inject()
  ctx: Context;

  @Config("jwt")
  jwtConfig: { secret: string; expiresIn: string };

  @Config("jwtCookieKey")
  jwtCookieKey: string;

  @Inject()
  captchaService: CaptchaService;

  @Inject()
  utils: Utils;

  @InjectEntityModel(User)
  userModel: Repository<User>;

  @Inject()
  userService: UserService;

  async get_current_user(token: string) {
    const result = (await this.jwtService.verify(token, {
      complete: true
    })) as any;
    const payload = result.payload;
    return this.utils.service.success({
      userId: payload.userId,
      account: payload.account
    });
  }

  async login(
    account: string,
    password: string,
    captchaId: string,
    captchaCode: string,
    isTest: boolean = false
  ) {
    // 测试模式下，不校验验证码
    if (!isTest) {
      const isok = await this.captchaService.check(captchaId, captchaCode);
      if (!isok) return { success: false, message: "验证码错误" };
    }

    // TODO 数据库查询用户信息
    // TODO jwt加密用户信息，包括用户id、用户名、密码、角色、权限等
    const result = await this.userService.findUserByAccountAndPassword(
      account,
      password
    );

    if (result.success) {
      const user = result.data as User;

      // 方便开发，测试用
      const token = await this.jwtService.sign({
        userId: user.userId,
        account: user.account
      });

      this.ctx.cookies.set(this.jwtCookieKey, token, {
        httpOnly: true,
        expires: new Date(Date.now() + 2 * 60 * 60 * 1000)
      });

      user.lastLoginIp = this.ctx.ip;
      user.lastLoginTime = new Date();

      this.userService.update(user);

      return this.utils.service.success(token);
    } else {
      return result;
    }
  }

  async checkCaptcha(captchaId: string, captchaCode: string) {
    return await this.captchaService.check(captchaId, captchaCode);
  }

  async createCaptcha() {
    return await this.captchaService.image({
      width: 120,
      height: 40,
      type: "mixed"
    });
  }
}
